package com.superbytecode.cloud.web.datetime;

import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.boot.convert.ApplicationConversionService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.FormatterRegistry;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

/**
 * All rights Reserved, Designed By www.super-master.com
 *
 * @ProjectName: beacon-cloud
 * @Package: com.superbytecode.cloud.web.configure
 * @ClassName: DatetimeConfiguration
 * @Description: [日期转换器配置，全局统一]
 * <p> 注意：字段手动配置@JsonFormat 注解将不再生效 </p>
 * @Author: [Lance Ting]
 * @Date: 2024/10/22 9:39
 * @Version: V1.0
 * @Copyright: 2024 www.super-master.cn Inc. All rights reserved.
 * TODO: 注意,本文件Lance Ting所作,如果转载或使用请标明具体出处!
 **/
@Configuration
public class DatetimeConfiguration {
    /**
     * Date格式化字符串
     **/
    private static final String DATE_FORMAT = "yyyy-MM-dd";
    /**
     * DateTime格式化字符串
     **/
    private static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    /**
     * Time格式化字符串
     **/
    private static final String TIME_FORMAT = "HH:mm:ss";

    /**
     * Jackson配置LocalDateTime和LocalDate的转换规则.
     * <p>
     * 为RequestBody和ResponseBody配置的转换格式
     * </p>
     */
    @Bean
    @Primary
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATETIME_FORMAT);
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(TIME_FORMAT);
        return builder -> builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter))//
                .serializerByType(LocalDate.class, new LocalDateSerializer(dateFormatter))//
                .serializerByType(LocalTime.class, new LocalTimeSerializer(timeFormatter))//
                //
                .deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter))//
                .deserializerByType(LocalDate.class, new LocalDateDeserializer(dateFormatter))//
                .deserializerByType(LocalTime.class, new LocalTimeDeserializer(timeFormatter))//
                ;
    }

    /**
     * RequestParam配置的转换格式LocalData
     * <p>
     *
     * @see ApplicationConversionService#addBeans(FormatterRegistry, ListableBeanFactory)
     * 使用springboot自动注入Converter特性实现
     * </p>
     */
    @Component
    public static class LocalDateConverter implements Converter<String, LocalDate> {
        @Override
        public LocalDate convert(@NonNull String source) {
            return LocalDate.parse(source, DateTimeFormatter.ofPattern(DATE_FORMAT));
        }
    }

    /**
     * RequestParam配置的转换格式LocalDateTime
     */
    @Component
    public static class LocalDateTimeConverter implements Converter<String, LocalDateTime> {
        @Override
        public LocalDateTime convert(@NonNull String source) {
            return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(DATETIME_FORMAT));
        }
    }
}